local e_util = require "libs/entutil"
local t_util = require "libs/tableutil"
local c_util = require "libs/calcutil"
local h_util = require "libs/hudutil"
local s_mana = require "libs/settingmanager"
local save_id = "auto_oceanfishing"
local p_util = require "libs/playerutil"
local data = s_mana:GetSettingLine(save_id)
data.turn = type(data.turn) == "nil" and true or data.turn
local _G = GLOBAL


------------------------------------自动海钓--------------------------------

local id_thread = "hx_OCEAN_FISHING"
local thread
local function StopThread()
    if not thread then return end
    GLOBAL.KillThreadsWithID(id_thread)
    thread = nil
end
AddPlayerActivatedFunc(function(player, world)
    local PC = player.components.playercontroller
    local PI = player.components.playeractionpicker
    if not PC or not PI then
        return
    end
    player:ListenForEvent("movectrl_withhx", StopThread)

    local _OnRightClick = PC.OnRightClick
    function PC:OnRightClick(down)
        local result = _OnRightClick(self, down)
        if down then
            local act = self:GetRightMouseAction()
            local act_id = act and act.action and act.action.id
            if act_id == "OCEAN_FISHING_CAST" and not thread and data.turn then
                thread = _G.StartThread(function()
                    local click_pos = _G.TheInput:GetWorldPosition()
                    local floater, floater_pos, fish
                    local flag = "搜寻鱼钩"
                    while thread and player do
                        if flag == "搜寻鱼钩" then
                            floater = e_util:FindEnt(click_pos, nil, 24, {"fishinghook"}, nil, nil, nil, function(e)
                                return type(e.spawntime) == "number" and _G.GetTime() - e.spawntime < 1
                            end)
                            if floater then
                                flag = "鱼钩标记"
                            else
                                if e_util:IsAnim(function(anim)return anim:find("idle")end, player) then
                                    flag = "重新抛竿"
                                end
                            end
                        elseif flag == "鱼钩标记" then
                            if e_util:IsValid(floater) then
                                local pos = floater:GetPosition()
                                if pos and pos.x~=0 and pos.z~=0 then
                                    floater_pos = pos
                                end
                            else
                                -- 其实关于上钩的判断有太多办法了
                                -- 检查控制器动作、检查鱼钩消失、检查鱼的动画、检查玩家的动画等等
                                local fishes = e_util:FindEnts(floater_pos, nil, 2, {"oceanfishable"}, {"fx", "inlimbo"})
                                fish = t_util:GetElement(fishes, function(_, e)
                                    return e_util:IsAnim(function(anim) return anim:find("struggle_") end, e) and e
                                end) or fishes[1]
                                if fish then
                                    flag = "上钩了"
                                else
                                    print("找不到鱼, 重新抛竿")
                                    flag = "重新抛竿"
                                end
                            end
                        elseif flag == "上钩了" then
                            local anim = e_util:GetAnim(fish)
                            if anim then
                                local fish_pos = fish:GetPosition()
                                local act = p_util:GetAction("point", {"OCEAN_FISHING_REEL", "OCEAN_FISHING_CATCH"}, true, p_util:GetEquip(_G.EQUIPSLOTS.HANDS), fish_pos)
                                if act then
                                    if anim:find("walk_") or anim:find("catching_") or anim:find("struggle_") then
                                        p_util:DoAction(act, _G.RPC.ControllerAltActionButtonPoint, act.action.code, fish_pos.x, fish_pos.z)
                                    elseif anim:find("run_") then     -- 挣扎
                                    elseif anim:find("breach") or anim:find("spawn") then       -- 消失
                                        flag = "重新抛竿"
                                    end
                                end
                            else
                                print("鱼的动画消失, 重新抛竿")
                                flag = "重新抛竿"
                            end
                        elseif flag == "重新抛竿" then
                            local p_pos = player:GetPosition()
                            local fish = e_util:FindEnt(click_pos, "icefishing_hole", 4, nil, {'INLIMBO', 'player'}) or e_util:FindEnt(p_pos, nil, 20, {"oceanfishable"}, {"fx", "inlimbo"})
                            local c_pos = fish and fish:GetPosition() or click_pos
                            if c_util:GetDist(p_pos.x, p_pos.z, c_pos.x, c_pos.z) < 40 then
                                local act = p_util:GetAction("point", "OCEAN_FISHING_CAST", true, p_util:GetEquip(_G.EQUIPSLOTS.HANDS), click_pos)
                                if act then
                                    p_util:DoAction(act, _G.RPC.ControllerAltActionButtonPoint, act.action.code, c_pos.x, c_pos.z)
                                    click_pos = c_pos
                                    flag = "搜寻鱼钩"
                                end
                            end
                            if flag ~= "搜寻鱼钩" then
                                print("咦，结束了")
                                break
                            end
                        end
                        _G.Sleep(_G.FRAMES*3)
                    end
                end, id_thread)
            end
        end
        return result
    end
end)

----------------------------------鱼群名字---------------------------------
local seasonal_fish = {
    "oceanfish_medium_8",
    "oceanfish_small_6",
    "oceanfish_small_7",
    "oceanfish_small_8",
}
local function AddFishName(fish)
    if fish._hx_label then
        if data.turn then
            fish._hx_label:SetText(fish.name)
        else
            fish._hx_label:SetText("")
        end
    else
        if data.turn then
            local label = h_util:CreateLabel(fish, fish.name, nil, _G.CHATFONT_OUTLINE, 30)
            if fish.prefab then
                local function setcolor(color)
                    if label and label.text then
                        label.text:SetColour(_G.unpack(_G.PLAYERCOLOURS[color]))
                    end
                end
                if table.contains(seasonal_fish, fish.prefab) then
                    setcolor("CORAL")
                else
                    local state = _G.TheWorld and _G.TheWorld.state
                    if state.isspring then
                        setcolor("GRASS")
                    elseif state.issummer then
                        setcolor("LAVENDER")
                    elseif state.isautumn then
                        setcolor("OTHERYELLOW")
                    end
                end
            end
        end
    end
end
for i = 1,9 do
    AddPrefabPostInit("oceanfish_medium_"..i, AddFishName)
    AddPrefabPostInit("oceanfish_small_"..i, AddFishName)
end

local function fn()
    data.turn = not data.turn
    s_mana:SaveSettingLine(save_id, data)
    local fishes = e_util:FindEnts(nil, nil, nil, {"oceanfishable", "oceanfishinghookable"}, {'INLIMBO', 'player'})
    if data.turn then
        TIP("海钓助手", "green", "开启，将会在下次抛竿时启用")
    else
        TIP("海钓助手", "red", "关闭, 将会在下次抛竿时禁用")
    end
    t_util:IPairs(fishes, AddFishName)
end

if GetModConfigData("sw_fishname") == "biubiu" then
    DEAR_BTNS:AddDearBtn(GLOBAL.GetInventoryItemAtlas("oceanfish_small_7_inv.tex"), "oceanfish_small_7_inv.tex", "海钓助手", "自动拉杆+显示云群名字", true, fn)
else
    AddBindBtn("sw_fishname", fn)
end
